package org.lex.notepad.ui.filechooser;

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Locale;

import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingWorker;


import org.lex.io.IO;
import org.lex.notepad.Notepad;
import org.lex.notepad.ui.NotepadEditor;
import org.lex.notepad.util.CK;
import org.lex.notepad.util.CharsetUtils;
import org.lex.swing.widgets.CharsetSelectorComboBox;

public class PreviewPane extends JPanel {
	private static final int MAX_BYTES_TO_READ = 1024 * 5;
	// ========================================
	private CharsetSelectorComboBox charsetsComboBox = null;
	private JScrollPane scrollPane = null;
	private NotepadEditor textArea = null;
	private JPanel encodingPane = null;
	private JLabel encodingLabel = null;
	private JFileChooser fc = null;
	// ========================================
	private Charset charset = null;
	private byte[] buffer = null;
	private int length = 0;

	public PreviewPane(JFileChooser fc) {
		super();
		this.fc = fc;
		this.buffer = new byte[MAX_BYTES_TO_READ];
		String charsetName = Notepad.getApplication().getContext().getResourceManager().getResourceMap().getString(CK.EDITOR_ENCODING);
		if (null == charsetName || charsetName.isEmpty())
			this.charset = Charset.defaultCharset();
		else
			this.charset = Charset.forName(charsetName);
		this.initialize();
	}

	public Charset getCharset() {
		return charset;
	}

	private void setCharset(Charset cs) {
		try {
			this.charset = cs;
			if (0 == length)
				return; // file not loaded or file is empty
			ByteArrayInputStream in = new ByteArrayInputStream(buffer, 0, length);
			NotepadEditor editor = this.getTextArea();
			editor.setCharset(cs);
			editor.read(in);
			editor.setCaretPosition(0);
		} catch (Exception e) {
		}
	}

	// =======================
	private void initialize() {
		BorderLayout borderLayout1 = new BorderLayout();
		borderLayout1.setVgap(5);
		this.setLayout(borderLayout1);
		this.setSize(100, 200);
		this.add(getEncodingPane(), BorderLayout.NORTH);
		this.add(getScrollPane(), BorderLayout.CENTER);
		this.fc.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, new FileLoader());
	}

	private CharsetSelectorComboBox getCharsetsComboBox() {
		if (charsetsComboBox == null) {
			charsetsComboBox = new CharsetSelectorComboBox(CharsetUtils.getCharsets(Locale.getDefault()));
			charsetsComboBox.setSelectedCharset(charset);
			this.charsetsComboBox.addCharsetChangeListener(new PropertyChangeListener() {
				public void propertyChange(PropertyChangeEvent evt) {
					Charset cs = getCharsetsComboBox().getSelectedCharset();
					setCharset(cs);
				}
			});
		}
		return charsetsComboBox;
	}

	private JScrollPane getScrollPane() {
		if (scrollPane == null) {
			scrollPane = new JScrollPane();
			scrollPane.setViewportView(getTextArea());
		}
		return scrollPane;
	}

	private NotepadEditor getTextArea() {
		if (textArea == null) {
			textArea = new NotepadEditor();
			textArea.setLineWrap(true);
			textArea.setAutoScrollText(false);
			textArea.setCharset(this.charset);
		}
		return textArea;
	}

	private JPanel getEncodingPane() {
		if (encodingPane == null) {
			BorderLayout borderLayout = new BorderLayout();
			borderLayout.setHgap(5);
			encodingLabel = new JLabel();
			encodingLabel.setText("Encoding");
			encodingLabel.setDisplayedMnemonic(KeyEvent.VK_E);
			encodingLabel.setLabelFor(this.getCharsetsComboBox());
			encodingPane = new JPanel();
			encodingPane.setLayout(borderLayout);
			encodingPane.add(getCharsetsComboBox(), BorderLayout.CENTER);
			encodingPane.add(encodingLabel, BorderLayout.WEST);
		}
		return encodingPane;
	}

	/**
	 * JFileChooser selected file changed property listener
	 */
	class FileLoader implements PropertyChangeListener {
		public void propertyChange(PropertyChangeEvent e) {
			final File file = fc.getSelectedFile();
			if (null == file || false == file.exists() || false == file.isFile()) {
				getTextArea().clear();
				length = 0;
				return;
			}
			new SwingWorker<Void, Void>() {
				@Override
				protected Void doInBackground() throws Exception {
					length = 0;
					InputStream in = null;
					try {
						/*
						 * step 1: read file ( in raw byte ) into byte-buffer
						 * step 2: use NotepadTextArea().setCharset(Charset) to
						 * change file encoding step 3: show on textarea
						 */
						in = new BufferedInputStream(new FileInputStream(file), buffer.length);
						length = in.read(buffer);
						setCharset(charset);
					} catch (IOException ioe) {
					} finally {
						IO.closeQuietly(in);
					}
					return null;
				}
			}.execute();
		}
	}
}
